<script setup>
import { dict, useTypes, compute } from '@fast-crud/fast-crud'
import ServerNameInput from './server-name-input.vue'
import { merge } from 'lodash-es'
import http from '@/http'
import {
  diskTypeDict,
  netChargemodeDict,
  netSharetypeDict,
  serverChargingModeDict,
  serverPeriodTypeDict
} from '@/use/dicts'

const props = defineProps({
  baseFormData: {
    type: Object,
    default: () => ({})
  }
})
const nowTime = new Date().getTime()
const projectDict = inject('projectDict')
const crudTypes = useTypes()
const form2Ref = ref(null)
const getFormRef = () => unref(form2Ref)?.getFormRef?.()
const doSubmit = () => unref(form2Ref)?.submit?.()
const transformDictQuery = () => {
  const findProject = projectDict.getNodeByValue(props.baseFormData.projectID)
  return {
    region: findProject?.name,
    domain: props.baseFormData.domain,
    ak: props.baseFormData.ak,
    sk: props.baseFormData.sk,
    productType: props.baseFormData.region,
    projectID: props.baseFormData.projectID
  }
}
const imageDict = dict({
  label: 'name',
  value: 'id',
  async getData() {
    const res = await http.post('/image/find_huawei_cloud', transformDictQuery())
    return res || []
  }
})
const keypairDict = dict({
  async getData() {
    const res = await http.post('/keypair/find_huawei_cloud', transformDictQuery())
    return (res || []).map((el) => ({
      label: el,
      value: el
    }))
  }
})
const availabilityZoneDict = dict({
  async getData() {
    const res = await http.post('/availabilityzone/find_huawei_cloud', transformDictQuery())
    return (res || []).map((el) => ({
      label: el,
      value: el
    }))
  }
})
const flavorDict = dict({
  label: 'name',
  value: 'name',
  async getData() {
    const res = await http.post('/specification/find', transformDictQuery())
    return res || []
  }
})
const vpcDict = dict({
  label: 'name',
  value: 'id',
  async getData() {
    const res = await http.post('/vpc/find_huawei_cloud', transformDictQuery())
    return res || []
  }
})
const subnetDict = dict({
  label: 'name',
  value: 'id',
  async getData() {
    const vpc = unref(form2Ref)?.getFormData?.()?.vpc
    if (!vpc) {
      return []
    }
    const res = await http.post('/subnet/find_huawei_cloud', {
      ...transformDictQuery(),
      vpc
    })
    return res || []
  },
  immediate: false
})
const securityGroupDict = dict({
  label: 'name',
  value: 'id',
  async getData() {
    const vpc = unref(form2Ref)?.getFormData?.()?.vpc
    if (!vpc) {
      return []
    }
    const res = await http.post('/securitygroup/find_huawei_cloud', {
      ...transformDictQuery(),
      vpc
    })
    return res || []
  },
  immediate: false
})
const formData = ref({})

const form2Options = ref({
  row: {
    gutter: 20
  },
  col: {
    span: 12
  },
  labelAlign: 'left',
  labelCol: {
    span: 8
  },
  columns: {
    name: {
      title: '服务器名称',
      component: merge({}, crudTypes.getType('text').form.component, {
        name: shallowRef(ServerNameInput),
        nowTime
      }),
      rules: [
        {
          required: true,
          message: '请输入'
        }
      ]
    },
    password: {
      title: '服务器管理员密码',
      helper: `必须包含有大写字母，数字，和特殊字符，长度不能小于8位`,
      component: merge({}, crudTypes.getType('text').form.component, {
        name: 'a-input-password'
      }),
      rules: [
        {
          validator(_, value) {
            if (value.length < 8) {
              return Promise.reject('密码长度不能小于8位')
            } else if (!/^(?=.*\d)(?=.*[A-Z])(?=.*[^\da-zA-Z\s])/.test(value)) {
              return Promise.reject('必须有大写字母，数字，和特殊字符')
            }
            return Promise.resolve()
          },
          trigger: 'change'
        }
      ]
    },
    flavor: {
      title: '服务器规格',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: flavorDict
      }),
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ]
    },
    keypair: {
      title: '密钥',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: keypairDict,
        allowClear: true
      })
    },
    image: {
      title: '产品镜像',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: imageDict
      }),
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ],
      valueChange({ form }) {
        const findImage = imageDict.getNodeByValue(form.image)
        if (findImage) {
          form.imageName = findImage.name
          const minDiskSize = Number(findImage?.minDisk)
          form.diskSize = minDiskSize
          getFormRef().clearValidate(['diskSize'])
        }
      }
    },
    diskSize: {
      title: '磁盘大小',
      component: merge({}, crudTypes.getType('number').form.component, {
        min: compute(({ form }) => {
          return Number(imageDict.getNodeByValue(form.image)?.minDisk) || 0
        }),
        max: 1024,
        addonAfter: 'GB'
      }),
      rules: [
        {
          required: true,
          type: 'number',
          message: '请输入'
        }
      ]
    },

    diskType: {
      title: '磁盘类型',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: diskTypeDict
      }),
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ]
    },

    vpc: {
      title: 'VPC',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: vpcDict,
        allowClear: true
      }),
      valueChange({ form }) {
        if (form.vpc) {
          subnetDict.reloadDict()
          securityGroupDict.reloadDict()

          const findOne = vpcDict.getNodeByValue(form.vpc)
          if (findOne) {
            form.vpcName = findOne.name
          }
        }
        form.subnet = null
        form.securityGroup = null
      },
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ]
    },
    subnet: {
      title: '子网',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: subnetDict,
        allowClear: true,
        disabled: compute(({ form }) => !form.vpc)
      }),
      valueChange({ form }) {
        const findOne = subnetDict.getNodeByValue(form.subnet)
        if (findOne) {
          form.subnetName = findOne.name
        }
      },
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ]
    },
    netChargemode: {
      title: '公网付费方式',
      component: merge({}, crudTypes.getType('dict-radio').form.component, {
        optionName: 'a-radio-button',
        dict: netChargemodeDict
      }),
      valueChange({ form }) {
        if (form.netChargemode === 'traffic') {
          form.serverChargingMode = 'postPaid'
        }
      },
      valueBuilder({ form }) {
        form.netChargemode = form.netChargemode === null ? 'null' : form.netChargemode
      },
      valueResolve({ form }) {
        form.netChargemode = form.netChargemode === 'null' ? null : form.netChargemode
      }
    },
    netSharetype: {
      title: '公网类型',
      component: merge({}, crudTypes.getType('dict-radio').form.component, {
        optionName: 'a-radio-button',
        dict: netSharetypeDict
      })
    },

    netBandwidth: {
      title: '公网带宽',
      component: merge({}, crudTypes.getType('number').form.component, {
        min: 0,
        max: 2000,
        addonAfter: 'Mbits/s'
      }),
      rules: [
        {
          required: true,
          type: 'number',
          message: '请选择'
        }
      ]
    },

    securityGroup: {
      title: '安全组',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: securityGroupDict,
        allowClear: true,
        disabled: compute(({ form }) => !form.vpc)
      }),
      valueChange({ form }) {
        const findOne = securityGroupDict.getNodeByValue(form.securityGroup)
        if (findOne) {
          form.securityGroupName = findOne.name
        }
      }
    },
    availabilityZone: {
      title: '可用区域',
      component: merge({}, crudTypes.getType('dict-select').form.component, {
        dict: availabilityZoneDict,
        allowClear: true
      })
    },
    serverChargingMode: {
      title: '服务器付费方式',
      component: merge({}, crudTypes.getType('dict-radio').form.component, {
        optionName: 'a-radio-button',
        disabled: compute(({ form }) => form.netChargemode === 'traffic'),
        dict: serverChargingModeDict
      }),
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ]
    },
    serverPeriodType: {
      title: '服务器付费周期',
      component: merge({}, crudTypes.getType('dict-radio').form.component, {
        optionName: 'a-radio-button',
        dict: serverPeriodTypeDict
      }),
      rules: [
        {
          required: true,
          message: '请选择'
        }
      ]
    },
    serverPeriodAmount: {
      title: '购买数量',
      component: merge({}, crudTypes.getType('number').form.component, {
        min: 1,
        addonAfter: compute(({ form }) => (form.serverPeriodType === 'month' ? '月' : '年'))
      }),
      rules: [
        {
          required: true,
          type: 'number',
          message: '请输入'
        }
      ]
    }
  },
  initialForm: {
    serverPeriodAmount: 1,
    netBandwidth: 1,
    netChargemode: 'traffic',
    netSharetype: 'PER',
    serverChargingMode: 'postPaid',
    serverPeriodType: 'month',
    vpc: null,
    subnet: null,
    securityGroup: null,
    availabilityZone: null
  },
  doSubmit({ form }) {
    formData.value = form
  }
})
defineExpose({ getFormRef, formData, doSubmit })
</script>

<template>
  <fs-form ref="form2Ref" v-bind="form2Options" />
</template>

<style scoped lang="less"></style>
